﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using IsmsExplorer.Model.Iso27001;
using IsmsExplorer.Model.Documents;
using IsmsExplorer.Application;
using IsmsExplorer.Application.Documents;
using IsmsExplorer.Application.Iso27001;

namespace IsmsExplorer.IsmsDataImport.Parser {
    class IsmsDocumentToControlMapper {
        // ***************************************** Data *****************************************
        private int REPOSITORY_TYPE_FILESYSTEM = 1;
        
        public string LogFileName { get; set; }

        // ***************************************** Cosntruction *****************************************


        // ***************************************** Operations *****************************************
        
        internal void MapControlToDocuments(Dictionary<string, List<string>> controlToDocsMap) {
            InitialiseAndValidateState();
            StringBuilder sbLog = new StringBuilder();
            // Append a new line to separate this content from parser's early output.
            sbLog.AppendLine();
            sbLog.AppendLine("Attempting to map controls to documents..");
            try {
                // Go through each ISO control reference ID and map to documents!
                foreach (string refID in controlToDocsMap.Keys) {
                    sbLog.AppendFormat("Mapping documents for control: {0}", refID).AppendLine();
                    // Get the ISO control from DB.
                    Iso27001Control control = Iso27001ControlService.FindControlByReferenceID(refID);
                    if (control != null) {
                        Iso27001ControlDocumentation doc = new Iso27001ControlDocumentation();
                        doc.IsoControl = control;
                        doc.ProjectID = UserSession.CurrentProject.ID;                        
                        // Need to assign documents for each file name.
                        List<string> files = controlToDocsMap[refID];
                        foreach (string fileName in files) {
                            string nameOnly = Path.GetFileName(fileName);
                            //string pathOnly = Path.GetDirectoryName(fileName);
                            // Check if we have already created a document link for the filename.
                            // NOTE: the filename (a.k.a. file URL as we're in filesystem) is meant to be
                            //       unique in the database table for the same repository type.
                            IsmsDocumentLink docLink = DocumentService.FindByUrlInRepository(UserSession.CurrentProject.ID, fileName, REPOSITORY_TYPE_FILESYSTEM);
                            if (docLink == null) {
                                docLink = new IsmsDocumentLink() {
                                    DocumentID = Guid.NewGuid(),
                                    DocumentName = nameOnly,
                                    DocumentURL = fileName,
                                    RepositoryTypeID = REPOSITORY_TYPE_FILESYSTEM
                                };
                                DocumentService.SaveIsmsDocumentLink(docLink);
                                sbLog.AppendFormat("Saved document link for document: {0}", fileName).AppendLine();

                            } else {
                                sbLog.AppendFormat("Document link for document: {0} ALREADY EXISTS IN DB!", fileName).AppendLine();
                            }
                            // Add it to the documentation object.
                            doc.AddDocument(docLink);
                        }
                        // Now we need to save the actual association, between the document links and the control!
                        DocumentService.SaveIso27001ControlDocumentation(doc);
                        sbLog.AppendFormat("DONE mapping documents for control: {0}", refID).AppendLine();

                    } else {
                        sbLog.AppendFormat("ERROR: Failed to retrieve ISO control from database for Ref ID: {0}", refID).AppendLine();
                    }
                }

            } catch (Exception ex) {
                sbLog.AppendLine().Append("ERROR: ").AppendLine(ex.Message);
                throw;

            } finally {                
                // We are appending to an existing log file this time, the parser should have already produced one.
                WriteLogFile(sbLog, append: true);
            }
        }
        
        private void WriteLogFile(StringBuilder sbLog, bool append) {
            using (TextWriter tw = new StreamWriter(LogFileName, append)) {
                tw.Write(sbLog.ToString());
            }
        }
        private void InitialiseAndValidateState() {
            if (string.IsNullOrEmpty(LogFileName) || !File.Exists(LogFileName)) {
                throw new ArgumentException("Log file empty or does not exist");
            }

        }


    }
}
